package server

import (
	"fmt"
	"github.com/labstack/echo/v4"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/stretchr/testify/assert"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"testing"
	"time"
)

var (
	httpClient = http.Client{Timeout: 1 * time.Second}
	requests   = prometheus.NewCounterVec(prometheus.CounterOpts{Name: "abrakadabra"}, []string{"firstlabel"})
)

func TestMetrics(t *testing.T) {
	baseUrl, cls := prepareAndStartServer(t)
	defer cls()

	err := prometheus.Register(requests)
	if err != nil {
		t.Fatalf("failed to register metrics: %s", err)
	}

	_, err = httpClient.Get(fmt.Sprintf("%s/test-address", baseUrl))
	if err != nil {
		t.Fatalf("failed to get test-address: %s", err)
	}

	requests.WithLabelValues("first-value").Inc()

	response, err := httpClient.Get(fmt.Sprintf("%s/metrics", baseUrl))
	if err != nil {
		t.Fatalf("failed to get metrics: %s", err)
	}

	data, err := ioutil.ReadAll(response.Body)
	if err != nil {
		t.Fatalf("failed to read body: %s", err)
	}

	fmt.Println(string(data))
	assert.Contains(t, string(data), "echo_request_duration_seconds_bucket")
}

func prepareAndStartServer(t *testing.T) (string, func()) {
	t.Helper()

	server := NewServer(HttpServerProperties{Address: "0.0.0.0:0"}, true)

	server.GET("/test-address", func(c echo.Context) error {
		return c.NoContent(http.StatusOK)
	})

	errs := RunServers(server)

	go func() {
		for {
			select {
			case err := <-errs:
				t.Errorf("failed to run servers: %s", err)
			}
		}
	}()

	var address net.Addr
	for {
		if listener := server.Listener; listener != nil {
			if address = server.Listener.Addr(); address != nil {
				break
			}
		}
		time.Sleep(10 * time.Millisecond)
	}
	parts := strings.Split(address.String(), ":")

	baseUrl := fmt.Sprintf("http://localhost:%s", parts[len(parts)-1])

	return baseUrl, func() {
		if err := server.Close(); err != nil {
			t.Errorf("failed to close server: %s", err)
		}
	}
}
